package com.seven.commons.excel.easyexcel;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import org.apache.commons.collections.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @工程名:common-utils
 * @author: sevenDay
 * @时间: 2019/1/4 09:00
 * @描述: 封装阿里巴巴的Excel防止内存溢出
 */
public class EasyExcelUtils {

    /**
     * @descrp: 多sheel的方式分開讀取 EasyExcelFactory.getReader(null,null).getSheets();
     * 支持03,07的Excel的格式,注意全部按照字符串读取处理，Date类型会出错
     * @auther: sevenDay
     * @date: 2019/1/4 10:20
     * @param inputStream :输入流
     * @param sheetNo : sheetNo,目前只支持单个sheetNo
     * @param headLineNo :
     * @return : java.util.List<java.lang.Object>
     */
    public static List<Object> readLessExcel(InputStream inputStream, Integer sheetNo, Integer headLineNo, List<Integer> indexDate){

        BufferedInputStream in = new BufferedInputStream(inputStream);
        List<Object> data = null;
        try {
            data = EasyExcelFactory.read(in, new Sheet(sheetNo, headLineNo));
        }finally {
            try {
               if (!Objects.isNull( in)){
                   in.close();
               }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //处理List的事件类型
        if (CollectionUtils.isEmpty(indexDate)){
            return data;
        }
        int isize = data.size();
        for (int i=0;i<isize;i++){
            List<Object> o = (ArrayList<Object>)data.get(i);
            //注意优化点，indexDate的数据量毕竟比较小，元素的列可能比较多
            int indexSize = indexDate.size();
            for (int j=0;j<indexSize;j++){
                int ii = Integer.parseInt(indexDate.get(j).toString());
                String str = ExcelDateUtils.getExcelNumberConverToDate(Double.parseDouble(o.get(ii).toString()));
                o.remove(ii);
                o.add(ii,str);
            }
            data.remove(i);
            data.add(i,o);
        }
        return  data;
    }

    /**
     * @descrp:进行excel转化为对象列表
     * @auther: sevenDay
     * @date: 2019/1/4 10:47
     * @param inputStream :
     * @param sheetNo :
     * @param headLineNo :
     * @param clazz :
     * @return : java.util.List<java.lang.Object>
     */
    public static List<Object> readLessExcel(InputStream inputStream,Integer sheetNo,Integer headLineNo, Class<? extends BaseRowModel> clazz){

        BufferedInputStream in = new BufferedInputStream(inputStream);
        List<Object> data = null;
        try {
            data = EasyExcelFactory.read(in, new Sheet(sheetNo, headLineNo,clazz));
        }finally {
            try {
                if (!Objects.isNull( in)){
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return  data;
    }
    /**
     * @descrp:功能描述
     * @auther: sevenDay
     * @date: 2019/1/4 16:48
     * @param inputStream :
     * @param sheetNo : 读取的sheetNo
     * @param headLineNo : 抬头
     * @param clazz : 转化为实体类
     * @param listener : 监听器的处理
     * @return : boolean
     */
    public static boolean readMoreExcel(InputStream inputStream,Integer sheetNo,Integer headLineNo, Class<? extends BaseRowModel> clazz, ExcelListener  listener){

        BufferedInputStream in = new BufferedInputStream(inputStream);
        try {
            EasyExcelFactory.readBySax(in, new Sheet(sheetNo, headLineNo,clazz),listener);
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
        finally {
            try {
                if (!Objects.isNull( in)){
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return  true;
    }
    /**
     * @descrp:异步读取Excel的大数据量的处理
     * @auther: sevenDay
     * @date: 2019/1/7 10:33
     * @param inputStream :
     * @param sheetNo :
     * @param headLineNo :
     * @param listener :
     * @return : boolean
     */
    public static boolean readMoreExcel(InputStream inputStream, Integer sheetNo, Integer headLineNo, ReadExcelListener listener){


        BufferedInputStream in = new BufferedInputStream(inputStream);
        try {
            EasyExcelFactory.readBySax(in, new Sheet(sheetNo, headLineNo),listener);
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
        finally {
            try {
                if (!Objects.isNull( in)){
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return  true;
    }

    public static void exportExcelToPath(List<? extends BaseRowModel> list,
                                         Class<? extends BaseRowModel> clazz,
                                         Map<Integer,Integer> columIndexWidth,
                                         String sheetName,
                                         String fileName,
                                         ExcelStyleModel headStyle,ExcelStyleModel contentStyle){

        OutputStream out = null;
        try {
            out = new FileOutputStream(fileName);
            ExcelWriter writer = EasyExcelFactory.getWriter(out);
            //写第一个sheet, sheet1  数据全是List<String> 无模型映射关系
            Sheet sheet1 = new Sheet(1, 3,clazz);
            sheet1.setSheetName(sheetName);
            if (!Objects.isNull(columIndexWidth)){
                sheet1.setColumnWidthMap(columIndexWidth);
            }
            if (!Objects.isNull(headStyle)){
                ExcelStyleModel.setSheetHeadStyle(headStyle,sheet1);
            }
            if (!Objects.isNull(contentStyle)){
                ExcelStyleModel.setSheetHeadStyle(contentStyle,sheet1);
            }
            writer.write(list,sheet1);
            writer.finish();

        } catch (IOException e) {

            e.printStackTrace();
        }finally {
            try {
                if (out!=null){
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
   public static void exportExcel(List<? extends BaseRowModel> list,
                                  Class<? extends BaseRowModel> clazz,
                                  Map<Integer,Integer> columIndexWidth,
                                  String sheetName,
                                  String fileName,
                                  String errorMsg,
                                  HttpServletResponse response,
                                  ExcelStyleModel headStyle,ExcelStyleModel contentStyle){

        OutputStream out = null;
        try {
            out = response.getOutputStream();
            ExcelWriter writer = EasyExcelFactory.getWriter(out);
            //写第一个sheet, sheet1  数据全是List<String> 无模型映射关系
            Sheet sheet1 = new Sheet(1, 3,clazz);
            sheet1.setSheetName(sheetName);
            if (!Objects.isNull(columIndexWidth)){
                sheet1.setColumnWidthMap(columIndexWidth);
            }
            if (!Objects.isNull(headStyle)){
                ExcelStyleModel.setSheetHeadStyle(headStyle,sheet1);
            }
            if (!Objects.isNull(contentStyle)){
                ExcelStyleModel.setSheetHeadStyle(contentStyle,sheet1);
            }
            writer.write(list,sheet1);
            writer.finish();

            //server端反馈信息
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition",
                    "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

        } catch (IOException e) {
            //重置excel的情况，显示json的提示代码
            response.reset();
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/json; charset=utf-8");
            PrintWriter o = null;
            try {
                o = response.getWriter();
                o.write(errorMsg);
            } catch (IOException e1) {
                e1.printStackTrace();
            } finally {
                if (o != null) {
                    o.close();
                }
            }
        }finally {
            try {
                if (out!=null){
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
